package eureka

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"properties"
	"time"
	"utils"
)

// 结构体
type OurCustomTransport struct {
}

// 接口实现方法
func (t *OurCustomTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	// 处理一些事情 ...
	// 发起HTTP请求
	// 添加一些域到req.Header中
	return http.DefaultTransport.RoundTrip(req)
}

// 设置接口
func (t *OurCustomTransport) Client() *http.Client {
	return &http.Client{Transport: t}
}

var transport *OurCustomTransport = &OurCustomTransport{
//...
}
var Client *http.Client = transport.Client()

// 注册
func Regist() {
	var logcalIp string = utils.GetPulicIP()
	var instanceInfo properties.Instance = properties.NewDefaultInstanceInfo()
	instanceInfo.InstanceId = logcalIp + ":8088"
	instanceInfo.HostName = logcalIp
	instanceInfo.App = "cango-golang"
	instanceInfo.IpAddr = logcalIp
	instanceInfo.HomePageUrl = "http://" + logcalIp + ":8088/"
	instanceInfo.StatusPageUrl = "http://" + logcalIp + ":8088/info"
	instanceInfo.HealthCheckUrl = "http://" + logcalIp + ":8088/health"
	instanceInfo.VipAddress = "cango-golang"
	instanceInfo.SecureVipAddress = "cango-golang"
	instanceInfo.LeaseInfo.ServiceUpTimestamp = utils.GetTimestampString()
	var port properties.PortWapper = properties.PortWapper{Enabled: "true", Port: "8088"}
	instanceInfo.Port = port

	instance := make(map[string]properties.Instance)
	instance["instance"] = instanceInfo

	bytesData, err := json.Marshal(instance)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	fmt.Println(string(bytesData))

	reader := bytes.NewReader(bytesData)
	resp, err := Client.Post("http://10.42.0.56/eureka/apps/cango-golang", "application/json;charset=UTF-8", reader)
	utils.Check(err)
	defer resp.Body.Close()
	fmt.Println(resp.StatusCode)
	// 显示body
	body, err := ioutil.ReadAll(resp.Body)
	utils.Check(err)
	fmt.Println(string(body))
}

func Heart() {
	ticker := time.NewTicker(time.Second * 30)
	go func() {
		for _ = range ticker.C {
			var logcalIp string = utils.GetPulicIP()
			var instanceId = logcalIp + ":8088"
			req, err := http.NewRequest("PUT", "http://10.42.0.56/eureka/apps/cango-golang/"+instanceId, nil)
			utils.Check(err)
			resp, err := Client.Do(req)
			if err != nil {
				fmt.Println(utils.GetNow(), ": Heart Error")
			} else {
				defer resp.Body.Close()
				fmt.Println(utils.GetNow(), ":", resp.StatusCode)
			}

		}
	}()
}

func init() {
	// 最后执行
	defer logError()
	// 微服务注册
	Regist()
	// 微服务心跳
	Heart()
}

func logError() {
	// Painc用法是：用于抛出错误。
	// Recover()用法是：将Recover()写在defer中，并且在可能发生panic的地方之前，
	// 先调用此defer的东西（让系统方法域结束时，有代码要执行。）当程序遇到panic的时候（当然，也可以正常的调用出现的异常情况），
	// 系统将跳过后面的代码，进入defer，如果defer函数中recover()，则返回捕获到的panic的值。
	if e, ok := recover().(error); ok {
		log.Println("ERROR: ", e)
		//		log.Println(string(debug.Stack()))
	}
}
